home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / readcpm.arc / RCPM.ASM < prev    next >
Assembly Source File  |  1989-05-30  |  15KB  |  676 lines

  1.  
  2.     INCLUDE    C:\ASM\EQUATES.ASM
  3.  
  4.     INCLUDE    C:\ASM\MACROS.ASM
  5.  
  6. CSEG    SEGMENT    PARA    PUBLIC    'CODE'
  7.  
  8.     ASSUME    CS:CSEG,DS:CSEG
  9.  
  10.     ORG    0100H
  11.  
  12. ;
  13. ; This equate controls where the files are written.  If TO_Z80_DIR is EQUated
  14. ;  to 1, then all files read from the floppy will be written to the path
  15. ;  "C:\Z80".  If TO_Z80_DIR is EQUated to 0, then all files will be written to
  16. ;  the current default path.
  17. ;
  18. TO_Z80_DIR    EQU    1        ; Need to define it
  19.  
  20. DIR_ENTRY_SIZE    EQU    32        ; 32 bytes for each dir entry
  21. MAX_DIR_ENTRIES    EQU    64        ; Max number of dir entries
  22. NUM_TRACKS    EQU    78        ; Number of tracks to read (* 2)
  23. BLOCKS_PER_TRK    EQU    2        ; Number of logical blks per trk
  24. RECORDS_PER_BLK    EQU    16        ; # of logical (128-byte) records
  25.                     ;  per block
  26. SECTORS_PER_BLK    EQU    8        ; Number of physical (256-byte) sectors
  27.                     ;  per blk
  28. SECTOR_SIZE    EQU    256        ; Size of disk sector
  29. SHIFT        EQU    8        ; Log2 of sector size
  30. SPT        EQU    16        ; Sectors per track
  31. BYTES_PER_TRACK    EQU    SECTOR_SIZE*SECTORS_PER_BLK*BLOCKS_PER_TRK
  32. RETRY_COUNT    EQU    5        ; Retry count for floppy read
  33.  
  34. START    PROC    FAR
  35.  
  36.     CALL    INITIALIZE        ; Set up
  37.     CALL    LOAD_DISK        ; Read entire floppy into memory
  38.     CALL    WRITE_FILES        ; Write files according to dir
  39.     MOV    AX,4C00H        ; Exit w/no error
  40.     INT    21H
  41.  
  42. START    ENDP
  43.  
  44. ;
  45. ; Once-only initialization.  Reset SP, get current disk parameters, set up
  46. ;  table of addresses for blocks & track
  47. ;
  48. INITIALIZE    PROC    NEAR
  49.  
  50.     POP    SI            ; Save return address
  51.     CLI                ; Can't be interrupted...
  52.     LEA    SP,STACK_TOP        ;  while SP is changed
  53.     STI                ; Ints ok now
  54.     PUSH    SI            ; Put return address back
  55.     MOV    AX,351EH        ; Get INT 1EH vector.  This points
  56.     INT    21H            ;  to the diskette parameters.
  57.     MOV    OLD_DISK_PTR,BX
  58.     MOV    OLD_DISK_PTR+2,ES    ; Save old parameters...
  59.     PUSH    DS            ; Swap segments
  60.     PUSH    ES
  61.     POP    DS
  62.     POP    ES
  63.     MOV    SI,BX            ; Point to the current parameters
  64.     LEA    DI,DISK_TABLE        ; And the ones I want to set
  65.     MOV    CX,11            ; Copy old to new
  66.     REP    MOVSB
  67.     PUSH    CS
  68.     POP    DS
  69.     MOV    BYTE PTR BPS,SECTOR_SIZE/256    ; Reset bytes per sector
  70.     MOV    BYTE PTR DTL,0FFH    ; Still a mystery...
  71.     MOV    BYTE PTR EOT,SPT    ; Reset sectors per track
  72.     MOV    BYTE PTR HST,0        ; Set to no head settle time
  73.     MOV    BYTE PTR MST,0        ;  ... and no motor start delay
  74.     SUB    AX,AX            ; BIOS function 0
  75.     INT    13H            ; (reset diskette system)
  76.     LEA    DI,BLOCKS        ; Fill in the "BLOCKS" table
  77.     LEA    AX,STACK_TOP        ; Get last program addr
  78.     ADD    AX,16            ; Align on a para boundary
  79.     MOV    CL,4
  80.     SHR    AX,CL
  81.     MOV    CX,CS
  82.     ADD    AX,CX            ; Make it absolute
  83.     MOV    CX,NUM_TRACKS*BLOCKS_PER_TRK
  84. INIT_L1:
  85.     STOSW                ; Put away a table entry
  86.     ADD    AX,(BYTES_PER_TRACK/BLOCKS_PER_TRK)/16
  87.     LOOP    INIT_L1
  88.     MOV    TRACK_BUFFER,AX
  89.     RET
  90.  
  91. INITIALIZE    ENDP
  92.  
  93. ;
  94. ; Routine to load the entire floppy disk into RAM.  Track-to-block translation
  95. ;  is done once the track is in memory
  96. ;
  97. LOAD_DISK    PROC    NEAR
  98.  
  99.     MOV    AX,CS
  100.     MOV    DS,AX            ; Make sure the segs are local
  101.     MOV    ES,AX
  102.     LEA    DX,PUT_IN_DISK        ; Display prompt message
  103.     MOV    AH,9
  104.     INT    21H
  105.     MOV    AH,1            ; And read a character
  106.     INT    21H
  107.     CALL    CRLF
  108.     LEA    DX,LOADING_MESS        ; Let me know what's going on...
  109.     MOV    AH,9
  110.     INT    21H
  111.     LEA    DI,BLOCKS        ; Point to pointer table
  112.     MOV    CX,NUM_TRACKS        ; Number of tracks to read
  113. ;
  114. ; Note that track 0 & 1 (system tracks) are not read.
  115. ;
  116. LD_L1:
  117.     CALL    READ_SECTOR        ; Read in a track
  118.     INC    BYTE PTR CURR_HEAD    ; Indicate next head
  119.     AND    BYTE PTR CURR_HEAD,1    ; Mod 2
  120.     JNZ    LD_L2            ; If changes from 1 to 0,
  121.     INC    BYTE PTR CURR_TRACK    ;  go to next track
  122. ;
  123. LD_L2:
  124.     MOV    AX,1            ; Starting at sector 1,
  125.     CALL    COPY_BLOCK        ;  copy from the track to a block
  126.     INC    DI            ; Point to next table entry
  127.     INC    DI
  128.     MOV    AX,SECTORS_PER_BLK+1    ; Now start at next block
  129.     CALL    COPY_BLOCK        ; And copy
  130.     INC    DI
  131.     INC    DI
  132.     MOV    AL,'.'            ; Tell me that 1 more has been read
  133.     CALL    PCHAR
  134.     LOOP    LD_L1            ; Do all tracks but 0
  135.     CALL    CRLF
  136.     RET
  137.  
  138. LOAD_DISK    ENDP
  139.  
  140.  
  141. ;
  142. ; Routine to copy from the track buffer to the block at (DI^)^.  This routine
  143. ;  assumes an interleave ("skew" under CP/M) of 3:1; i.e., to read a block
  144. ;  starts at sector 1, the sectors must be read in this order:
  145. ;  1,4,7,10,13,16,3,6.  A block that starts on sector 9: 9,12,15,2,5,8,11,14.
  146. ;
  147. COPY_BLOCK    PROC    NEAR
  148.  
  149.     SAVE_REG    AX,CX,SI,DI,DS,ES
  150.     MOV    DS,CS:TRACK_BUFFER    ; Point to track buffer
  151.     MOV    ES,CS:[DI]        ; Need seg for this block
  152.     SUB    DI,DI            ; Copy to offset 0
  153.     MOV    CX,SECTORS_PER_BLK    ; This many sectors
  154. CB_L1:
  155.     PUSH    CX            ; Save outer loop count
  156.     MOV    SI,AX            ; Get sector number
  157.     DEC    SI            ; ......
  158.     MOV    CL,SHIFT        ; ......
  159.     SHL    SI,CL            ; Make it an offset
  160.     MOV    CX,SECTOR_SIZE        ; Move one sector to block buffer
  161.     REP    MOVSB
  162.     INC    AX            ; Calculate next sector to read
  163.     INC    AX            ; S = (S + 2)
  164.     AND    AX,0FH            ; S = ((S + 2) MOD 16)
  165.     INC    AX            ; S = ((S + 2) MOD 16) + 1
  166.     POP    CX
  167.     LOOP    CB_L1            ; Do all sectors in this block
  168.     RESTORE
  169.     RET
  170.  
  171. COPY_BLOCK    ENDP
  172.  
  173.  
  174. ;
  175. ; Control routine to copy files from the block buffers to the appropriate DOS
  176. ;  files according to the directory at BLOCK[0].
  177. ;
  178. WRITE_FILES    PROC    NEAR
  179.  
  180.     SAVE_REG    AX,BX,CX,SI,DI,DS,ES
  181.     SUB    BX,BX            ; Set up parameters
  182.     MOV    CX,MAX_DIR_ENTRIES    ; Number of entries to scan
  183. WF_L1:
  184.     PUSH    CX            ; Save the loop count
  185.     MOV    DS,CS:BLOCKS        ; Point to directory block
  186.     CMP    BYTE PTR [BX],0E5H    ; Is this a deleted file?
  187.     JE    WF_CONT            ; Continue the loop if it is
  188.     CMP    BYTE PTR [BX+12],2    ; Is this a continuation extent?
  189.     JAE    WF_CONT            ; Continue the loop if it is
  190.     MOV    CS:FILE_SIZE,0        ; Start with that record size
  191.     CALL    COPY_NAME        ; Copy the file name
  192.     PUSH    CS
  193.     POP    DS            ; Reset to local seg
  194.     CALL    ASK_ME            ; Ask me if I want to copy it
  195.     CMP    AL,'Y'            ; If I said "N", then ignore it
  196.     JNE    WF_CONT
  197.     CALL    OPEN_FILE        ; Open the output file
  198.     LEA    DX,WRITING_MESS        ; Tell me the file being written
  199.     MOV    AH,9
  200.     INT    21H
  201.     LEA    SI,FILE_NAME
  202.     CALL    PSTRING            ; Tell me the file name
  203.     CALL    PUT_FILE        ; Save the file
  204.     POP    CX
  205.     PUSH    CX
  206.     CALL    FIND_OTHERS        ; Find any other extents for that file
  207.     MOV    AL,';'            ; More info;
  208.     CALL    PCHAR
  209.     MOV    AL,SPACE
  210.     CALL    PCHAR
  211.     MOV    AX,CS:FILE_SIZE        ; Show file size in 128-byte records
  212.     CALL    PDECI
  213.     LEA    SI,RECS_MESS
  214.     CALL    PSTRING
  215.     CALL    CLOSE_FILE        ; Now close it
  216. ;
  217. WF_CONT:
  218.     ADD    BX,DIR_ENTRY_SIZE    ; Point to next entry
  219.     POP    CX            ; Restore the loop count
  220.     LOOP    WF_L1
  221.     RESTORE
  222.     RET
  223.  
  224. WRITE_FILES    ENDP
  225.  
  226.  
  227. ;
  228. ; This routine displays a single file name (from the floppy directory), and
  229. ;  prompts the user for a Y(es) or N(o) answer as to whether or not to copy
  230. ;  the named file.
  231. ;
  232. ASK_ME        PROC    NEAR
  233.  
  234.     SAVE_REG    DX,SI
  235.     LEA    DX,WRITE_QUERY
  236.     MOV    AH,9
  237.     INT    21H
  238.     LEA    SI,NAME_BUF
  239.     CALL    PSTRING
  240.     MOV    AL,'?'
  241.     CALL    PCHAR
  242.     MOV    AL,SPACE
  243.     CALL    PCHAR
  244.     CALL    YES_OR_NO
  245.     RESTORE
  246.     RET
  247.  
  248. ASK_ME        ENDP
  249.  
  250.  
  251. YES_OR_NO    PROC    NEAR
  252.  
  253.     MOV    AH,7
  254.     MOV    DL,0FFH
  255.     INT    21H
  256.     CMP    AL,'a'
  257.     JB    YORN_L1
  258.     CMP    AL,'z'+1
  259.     JAE    YORN_L1
  260.     SUB    AL,32
  261. YORN_L1:
  262.     CMP    AL,'Y'
  263.     JE    YORN_RET
  264.     CMP    AL,'N'
  265.     JNE    YES_OR_NO
  266. YORN_RET:
  267.     CALL    PCHAR
  268.     CALL    CRLF
  269.     RET
  270.  
  271. YES_OR_NO    ENDP
  272.  
  273.  
  274. ;
  275. ; Search the directory for any other entries matching the current entry,
  276. ;  and write them to the file, too.
  277. ;
  278. FIND_OTHERS    PROC    NEAR
  279.  
  280.     SAVE_REG    AX,BX,CX,SI,DI,DS,ES
  281.     MOV    DS,CS:BLOCKS        ; Point to the directory
  282.     MOV    ES,CS:BLOCKS        ; Twice
  283.     MOV    DI,BX            ; Get current entry
  284.     ADD    DI,DIR_ENTRY_SIZE    ; Point to next (to start)
  285.     DEC    CX            ; One less to search
  286. FO_L1:
  287.     MOV    SI,BX            ; Point to the current one
  288.     INC    SI            ; Skip user number
  289.     PUSH    DI            ; Save pointer to other
  290.     CMP    BYTE PTR ES:[DI],0E5H    ; Is this a deleted entry?
  291.     JE    FO_L2            ; If so, skip it
  292.     CMP    BYTE PTR ES:[DI+12],1    ; Is this a starting extent?
  293.     JBE    FO_L2            ; If so, skip it
  294.     INC    DI            ; Skip user number on this one
  295.     PUSH    CX            ; Save search count
  296.     MOV    CX,11            ; Compare 11 bytes
  297.     REPE    CMPSB            ; Names match?
  298.     POP    CX            ; Get search count back
  299.     JNZ    FO_L2            ; If no match, continue search
  300.     SUB    DI,12            ; Point to name again
  301.     XCHG    BX,DI            ; Save and point at same time
  302.     CALL    PUT_FILE        ; Put these blocks in the file
  303.     XCHG    BX,DI            ; Get the dir ptr back
  304. ;
  305. FO_L2:
  306.     POP    DI            ; Restore "other" pointer
  307.     ADD    DI,DIR_ENTRY_SIZE    ; Point to next
  308.     LOOP    FO_L1            ; Loop away
  309.     RESTORE
  310.     RET
  311.  
  312. FIND_OTHERS    ENDP
  313.  
  314.  
  315. ;
  316. ; Routine to copy the file name to ASCIIZ format for opening.
  317. ;
  318. COPY_NAME    PROC    NEAR
  319.  
  320.     SAVE_REG    AX,CX,SI,DI,DS
  321.     MOV    SI,BX            ; Point to the dir entry
  322.     INC    SI            ; Skip the user number
  323.     LEA    DI,NAME_BUF        ; Point to the file name area
  324.     MOV    CX,8            ; Max number to copy
  325.     CALL    COPY_PART        ; Copy the first part
  326.     MOV    AL,'.'            ; Put in the separator
  327.     STOSB
  328.     MOV    CX,3            ; Max number of bytes in ext
  329.     CALL    COPY_PART        ; Copy it
  330.     SUB    AL,AL            ; Terminate with a null
  331.     STOSB
  332.     RESTORE
  333.     RET
  334.  
  335. COPY_NAME    ENDP
  336.  
  337.  
  338. ;
  339. ; Routine to copy part of the file name from the dir entry to the local
  340. ;  copy of the file name.
  341. ;
  342. COPY_PART    PROC    NEAR
  343.  
  344.     LODSB                ; Pick up a byte
  345.     AND    AL,7FH            ; Don't care about 8th bit
  346.     CMP    AL,SPACE        ; Is it the end?
  347.     JE    CN_L1
  348.     STOSB                ; Put the byte away
  349. CN_L1:
  350.     LOOP    COPY_PART        ; Loop for whatever
  351.     RET                ; Return to caller
  352.  
  353. COPY_PART    ENDP
  354.  
  355.  
  356. ;
  357. ; Routine to open the file @FILE_NAME
  358. ;
  359. OPEN_FILE    PROC    NEAR
  360.  
  361.     SAVE_REG    AX,BX,CX,DX,DS
  362.     PUSH    CS
  363.     POP    DS
  364.     LEA    DX,FILE_NAME        ; Open the file @FILE_NAME
  365.     MOV    AH,3CH
  366.     SUB    CX,CX
  367.     INT    21H
  368.     JNC    OPFL_L1            ; If error then let me know
  369.     PUSH    AX
  370.     LEA    DX,OPEN_ERROR
  371.     MOV    AH,9
  372.     INT    21H            ; Display "open error" message
  373.     LEA    SI,FILE_NAME        ; Display the file name
  374.     CALL    PSTRING
  375.     MOV    AL,':'
  376.     CALL    PCHAR
  377.     POP    AX
  378.     CALL    PDECI
  379.     MOV    AX,4C01H
  380.     INT    21H            ; Exit w/error to DOS
  381. ;
  382. OPFL_L1:
  383.     MOV    HANDLE,AX        ; Save the file handle
  384.     RESTORE
  385.     RET
  386.  
  387. OPEN_FILE    ENDP
  388.  
  389.  
  390. ;
  391. ; Routine to close the current file
  392. ;
  393. CLOSE_FILE    PROC    NEAR
  394.  
  395.     SAVE_REG    AX,BX
  396.     MOV    AH,3EH
  397.     MOV    BX,CS:HANDLE
  398.     INT    21H
  399.     RESTORE
  400.     RET
  401.  
  402. CLOSE_FILE    ENDP
  403.  
  404.  
  405. ;
  406. ; Routine to copy the current block to the output file
  407. ;
  408. SAVE_FILE    PROC    NEAR
  409.  
  410.     SAVE_REG    AX,BX,CX,DX
  411.     MOV    BX,CS:HANDLE        ; Get the handle to write to
  412.     MOV    AX,CS:FILE_COUNT    ; Get number of bytes to write
  413.     MOV    CL,7
  414.     SHL    AX,CL
  415.     MOV    CX,AX
  416.     SUB    DX,DX            ; Write from offset 0...
  417.     MOV    AH,40H
  418.     INT    21H
  419.     JNC    SAVE_L1            ; If error occurred, tell me
  420.     PUSH    CS
  421.     POP    DS
  422.     LEA    DX,ERROR_MESS
  423.     MOV    AH,9
  424.     INT    21H
  425.     LEA    SI,FILE_NAME
  426.     CALL    PSTRING
  427.     CALL    CLOSE_FILE        ; Salvage what we can...
  428.     MOV    AX,4C02H
  429.     INT    21H
  430. ;
  431. SAVE_L1:
  432.     RESTORE
  433.     RET
  434.  
  435. SAVE_FILE    ENDP
  436.  
  437.  
  438. ;
  439. ; Routine to control which blocks get copied to the output file.  Reads the
  440. ;  list of blocks in the current dir entry.
  441. ;
  442. PUT_FILE    PROC    NEAR
  443.  
  444.     SAVE_REG    AX,CX,SI,DS
  445.     MOV    DS,CS:BLOCKS
  446.     MOV    SI,BX            ; Point to the current dir entry
  447.     ADD    SI,15            ; Point to the block list & size
  448.     MOV    CL,[SI]
  449.     SUB    CH,CH            ; Get number of records for this extent
  450.     TEST    BYTE PTR [SI-3],1    ; Is the extent number odd?
  451.     JZ    PUTF_L11        ; If not, leave record count alone
  452.     ADD    CX,80H            ; If extent number is odd, then it
  453.                     ;  means that there are 2 extents
  454.                     ;  referenced by the dir entry, and
  455.                     ;  the record count is for the 2nd
  456.                     ;  extent; the first extent takes up
  457.                     ;  80H(128d) records.  Adjust the
  458.                     ;  record count accordingly.
  459. PUTF_L11:
  460.     JCXZ    PUTF_RET        ; Return if size is 0
  461.     INC    SI            ; First block of file
  462.     MOV    AH,16            ; Max number of blocks per extent
  463. PUTF_L1:
  464.     LODSB                ; Pick up the block number
  465.     OR    AL,AL            ; Is it 0?
  466.     JZ    PUTF_RET        ; Return if so
  467.     CMP    CX,RECORDS_PER_BLK    ; Are there at least that many left?
  468.     JB    PUTF_L2            ; If not, just write that many.
  469.     SUB    CX,RECORDS_PER_BLK
  470.     MOV    CS:FILE_COUNT,RECORDS_PER_BLK
  471.     ADD    CS:FILE_SIZE,RECORDS_PER_BLK
  472.     JMP    SHORT PUTF_L3
  473. PUTF_L2:
  474.     MOV    CS:FILE_COUNT,CX
  475.     ADD    CS:FILE_SIZE,CX
  476. PUTF_L3:
  477.     PUSH    AX            ; Save the block number
  478.     PUSH    SI
  479.     PUSH    DS
  480.     SUB    AH,AH
  481.     SHL    AX,1
  482.     MOV    SI,AX
  483.     MOV    DS,CS:BLOCKS[SI]
  484.     CALL    SAVE_FILE
  485.     POP    DS
  486.     POP    SI
  487.     POP    AX
  488.     DEC    AH
  489.     JNZ    PUTF_L1            ; Loop for all blocks
  490. ;
  491. PUTF_RET:
  492.     RESTORE
  493.     RET
  494.  
  495. PUT_FILE    ENDP
  496.  
  497. ;
  498. ; Simple utility routines called by most of the above
  499. ;
  500. CRLF    PROC    NEAR
  501.  
  502.     PUSH    AX
  503.     MOV    AL,CR
  504.     CALL    PCHAR
  505.     MOV    AL,LF
  506.     CALL    PCHAR
  507.     POP    AX
  508.     RET
  509.  
  510. CRLF    ENDP
  511.  
  512.  
  513. PDECI    PROC    NEAR
  514.  
  515.     SAVE_REG    AX,BX,DX
  516.     SUB    BX,BX            ; Put a flag word on the stack
  517.     PUSH    BX
  518.     MOV    BX,10            ; Divisor for decimal conversion
  519. PDECI_L1:
  520.     SUB    DX,DX            ; Clear high word for division
  521.     DIV    BX            ; Divide number by 10
  522.     OR    DL,30H            ; Make the digit ASCII
  523.     PUSH    DX            ; And save it
  524.     OR    AX,AX            ; See if we're done yet
  525.     JNZ    PDECI_L1        ; If not, keep going
  526. PDECI_L2:
  527.     POP    AX            ; Get a previously saved digit
  528.     OR    AX,AX            ; See if it's the flag word
  529.     JZ    PDECI_L3        ; If it is, we're done
  530.     CALL    PCHAR            ; Display the digit
  531.     JMP    SHORT PDECI_L2        ; Do the rest
  532. ;
  533. PDECI_L3:
  534.     RESTORE
  535.     RET
  536.  
  537. PDECI    ENDP
  538.  
  539.  
  540. PSTRING    PROC    NEAR
  541.  
  542.     SAVE_REG    AX,SI,DS
  543.     PUSH    CS
  544.     POP    DS            ; Make sure seg is right
  545. PSTR_L1:
  546.     LODSB                ; Pick up a byte of the string
  547.     OR    AL,AL            ; Is it terminator?
  548.     JZ    PSTR_RET        ; If it is, exit
  549.     CALL    PCHAR
  550.     JMP    SHORT PSTR_L1
  551. ;
  552. PSTR_RET:
  553.     RESTORE
  554.     RET
  555.  
  556. PSTRING    ENDP
  557.  
  558.  
  559. PCHAR    PROC    NEAR
  560.  
  561.     SAVE_REG    AX,DX
  562.     MOV    DL,AL
  563.     MOV    AH,2
  564.     INT    21H
  565.     RESTORE
  566.     RET
  567.  
  568. PCHAR    ENDP
  569.  
  570.  
  571. ;
  572. ; Routine to read 1 track from the floppy
  573. ;
  574. READ_SECTOR    PROC    NEAR
  575.  
  576.     SAVE_REG    AX,BX,CX,DX,ES
  577.     MOV    AX,251EH
  578.     LEA    DX,DISK_TABLE
  579.     INT    21H            ; Set disk parameters
  580.     MOV    CX,RETRY_COUNT        ; Get the retry count
  581. ;
  582. READ_SECTOR_L1:
  583.     PUSH    CX            ; Save current retry count
  584.     SUB    DL,DL            ; Always use A: drive
  585.     MOV    DH,CS:CURR_HEAD        ; Pick up BIOS parameters
  586.     MOV    CL,1
  587.     MOV    CH,CS:CURR_TRACK
  588.     MOV    ES,CS:TRACK_BUFFER
  589.     SUB    BX,BX
  590.     MOV    AL,SPT
  591.     MOV    AH,2            ; Read 1 track
  592.     INT    13H            ; Via ROM BIOS
  593.     POP    CX
  594.     JNC    READ_SECTOR_L2        ; If no error, then finish
  595.     LOOP    READ_SECTOR_L1        ; Otherwise, keep re-trying
  596.     LEA    DX,FL_ERROR_MESS    ; Display the error message
  597.     PUSH    CS
  598.     POP    DS
  599.     MOV    AH,9
  600.     INT    21H
  601.     MOV    DX,CS:OLD_DISK_PTR
  602.     MOV    DS,CS:OLD_DISK_PTR+2
  603.     MOV    AX,251EH
  604.     INT    21H
  605.     MOV    AX,4C03H
  606.     INT    21H
  607. ;
  608. READ_SECTOR_L2:
  609.     PUSH    DS
  610.     MOV    DX,CS:OLD_DISK_PTR    ; Restore old parameters
  611.     MOV    DS,CS:OLD_DISK_PTR+2
  612.     MOV    AX,251EH
  613.     INT    21H
  614.     POP    DS
  615.     RESTORE
  616.     RET
  617.  
  618. READ_SECTOR    ENDP
  619.  
  620.  
  621. DISK_TABLE    DB    0
  622.         DB    0
  623.         DB    0
  624. BPS        DB    0
  625. EOT        DB    0
  626.         DB    0
  627. DTL        DB    0
  628.         DB    0
  629.         DB    0
  630. HST        DB    0
  631. MST        DB    0
  632.  
  633. OLD_DISK_PTR    DW    0
  634.         DW    0
  635.  
  636. CURR_HEAD    DB    0
  637. CURR_TRACK    DB    1
  638.  
  639. LOADING_MESS    DB    'Reading diskette',CR,LF,'$'
  640. PUT_IN_DISK    DB    'Put CP/M diskette in drive A:, then press any key $'
  641. OPEN_ERROR    DB    '? Error opening $'
  642. WRITE_QUERY    DB    'Copy $'
  643. WRITING_MESS    DB    'Writing $'
  644. RECS_MESS    DB    ' records written',CR,LF,0
  645. ERROR_MESS    DB    '? Error writing to $'
  646. FL_ERROR_MESS    DB    '? Error reading floppy drive',CR,LF,'$'
  647.  
  648.     IF    TO_Z80_DIR
  649. FILE_NAME    DB    'C:\Z80\'
  650.     ELSE
  651. FILE_NAME    LABEL    BYTE
  652.     ENDIF
  653. NAME_BUF    DB    13 DUP(0)
  654.  
  655. FILE_SIZE    DW    0
  656.  
  657. HANDLE        DW    0
  658.  
  659. TRACK_BUFFER    DW    0
  660.  
  661. BLOCKS        DW    NUM_TRACKS*BLOCKS_PER_TRK DUP(0)
  662.  
  663. FILE_COUNT    DW    0
  664. FILE_BUFFER    DW    0
  665.  
  666.     EVEN
  667.  
  668.     DW    256 DUP(0)
  669.  
  670. STACK_TOP    = $
  671.  
  672.  
  673. CSEG    ENDS
  674.  
  675.     END    START
  676.